package org.jeecg.modules.online.desform.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.online.desform.constant.PermissionTypeEnum;
import org.jeecg.modules.online.desform.entity.DesignFormAuth;
import org.jeecg.modules.online.desform.entity.DesignFormData;
import org.jeecg.modules.online.desform.mapper.DesignFormAuthMapper;
import org.jeecg.modules.online.desform.service.IDesignFormAuthService;
import org.jeecg.modules.online.desform.service.IDesignFormService;
import org.jeecg.modules.online.desform.util.DesformAuthUtils;
import org.jeecg.modules.online.desform.vo.ExtActProcessNodeAuth;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 表单设计器字段权限表
 * @Author: jeecg-boot
 * @Date: 2019-09-03
 * @Version: V1.0
 */
@Service("designFormAuthServiceImpl")
public class DesignFormAuthServiceImpl extends ServiceImpl<DesignFormAuthMapper, DesignFormAuth> implements IDesignFormAuthService {

    @Autowired
    ISysBaseAPI sysBaseAPI;
    @Autowired
    private IDesignFormService designFormService;

    private LambdaQueryWrapper<DesignFormAuth> getQueryWrapper(String desformCode) {
        LambdaQueryWrapper<DesignFormAuth> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DesignFormAuth::getDesformCode, desformCode);
        return queryWrapper;
    }

    @Override
    public List<DesignFormAuth> queryByCode(String desformCode, boolean isGroup) {
        LambdaQueryWrapper<DesignFormAuth> queryWrapper = this.getQueryWrapper(desformCode);
        if (isGroup) {
            queryWrapper.eq(DesignFormAuth::getAuthType, "1");
            //只查询表单字段授权
            queryWrapper.eq(DesignFormAuth::getPermissionType, "field");
        }
        return this.list(queryWrapper);
    }

    @Override
    public List<DesignFormAuth> queryByCode(String desformCode) {
        return this.queryByCode(desformCode, false);
    }

    @Override
    public List<DesignFormAuth> queryByCodeAndAuthComKey(String desformCode, String authComKey) {
        return this.list(this.getQueryWrapper(desformCode).eq(DesignFormAuth::getAuthComKey, authComKey));
    }

    @Override
    public List<DesignFormAuth> queryByTaskId(String desformCode, String taskId) {
        List<ExtActProcessNodeAuth> list = baseMapper.selectByTaskId(desformCode, taskId);

        List<DesignFormAuth> result = new ArrayList<>(list.size());
        for (ExtActProcessNodeAuth item : list) {
            DesignFormAuth auth = new DesignFormAuth();
            auth.setDesformCode(desformCode);
            //判断是否子表的权限字段格式  cc_tou_su_product_62428::product_name
            String authField = item.getRuleCode();
            if(authField!=null && authField.indexOf("::")!=-1){
                auth.setSubKey(authField.substring(0,authField.indexOf("::")));
                auth.setSubTable(true);
                auth.setAuthField(authField.substring(authField.indexOf("::")+2));
            }else{
                auth.setAuthField(authField);
                auth.setSubTable(false);
            }
            auth.setAuthComKey(item.getDesformComKey());
            auth.setAuthTitle(item.getRuleName());

            // 1=显示，2=禁用
            String ruleType = item.getRuleType();

            // 0=无效，1=有效
            // 无效状态下，配置了显示权限的组件皆为隐藏状态，配置了禁用的组件皆为可编辑状态
            // 有效状态下，配置了显示权限的组件皆为显示状态，配置了禁用的组件皆为已禁用状态
            String status = item.getStatus();

            if ("0".equals(status)) {
                if ("1".equals(ruleType)) {
                    auth.setAuthScopeIsAll("N");
                } else {
                    auth.setAuthScopeIsAll("Y");
                }
            } else {
                if ("1".equals(ruleType)) {
                    auth.setAuthScopeIsAll("Y");
                } else {
                    auth.setAuthScopeIsAll("N");
                }
            }
            auth.setAuthType(ruleType);
            auth.setPermissionType("field");
            auth.setStatus(1);

            result.add(auth);
        }

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateBatch(List<DesignFormAuth> auths) {
        for (DesignFormAuth auth : auths) {
            LambdaQueryWrapper<DesignFormAuth> queryWrapper = new LambdaQueryWrapper<>();
            if (StringUtils.isEmpty(auth.getId())) {
                queryWrapper.eq(DesignFormAuth::getDesformCode, auth.getDesformCode());
                queryWrapper.eq(DesignFormAuth::getAuthComKey, auth.getAuthComKey());
                if (!StringUtils.isEmpty(auth.getAuthType())) {
                    queryWrapper.eq(DesignFormAuth::getAuthType, auth.getAuthType());
                }
            } else {
                queryWrapper.eq(DesignFormAuth::getId, auth.getId());
            }
            this.update(auth, queryWrapper);
        }
        return true;
    }

    @Override
    public JSONObject getUserInfoByUsername(String username) {
        LoginUser userInfo = sysBaseAPI.getUserByName(username);

        if (userInfo == null) {
            throw new JeecgBootException("用户不存在");
        }

        List<String> roles = sysBaseAPI.getRolesByUsername(username);
        List<String> departs = sysBaseAPI.getDepartIdsByUsername(username);

        JSONObject json = new JSONObject(3);
        json.put("userInfo", userInfo);
        json.put("roles", roles);
        json.put("departs", departs);
        return json;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean initialAuthInfo(DesignFormAuth auth) {
        auth.setAuthScopeIsAll("Y");
        if (auth.getSubTable() == null) {
            auth.setSubTable(false);
        }
        auth.setStatus(1);
        auth.setPermissionType("field");

        List<DesignFormAuth> authList = new ArrayList<>();

        // 添加可见权限
        DesignFormAuth authTemp = new DesignFormAuth();
        BeanUtils.copyProperties(auth, authTemp);
        authTemp.setAuthType("1");
        authList.add(authTemp);

        // 添加可编辑权限
        authTemp = new DesignFormAuth();
        BeanUtils.copyProperties(auth, authTemp);
        authTemp.setAuthType("2");
        authList.add(authTemp);

        return this.saveBatch(authList);
    }

    @Override
    public boolean checkPermissionType(String permissionType) {
        PermissionTypeEnum type = PermissionTypeEnum.getByValue(permissionType);
        if (type != null) {
            return true;
        }
        throw new JeecgBootException("不识别的permissionType值");
    }

    @Override
    public IPage<DesignFormAuth> pageList(Integer pageNo, Integer pageSize, Wrapper<DesignFormAuth> wrapper) {
        if (pageNo == null) {
            pageNo = 1;
        }
        if (pageSize == null) {
            pageSize = 10;
        }
        // -1 不分页
        if (pageNo == -1) {
            IPage<DesignFormAuth> pageList = new Page<>();
            List<DesignFormAuth> list = super.list(wrapper);
            pageList.setRecords(list);
            pageList.setTotal(list.size());
            return pageList;
        } else {
            return super.page(new Page<>(pageNo, pageSize), wrapper);
        }
    }

    @Override
    public boolean addAuthByPermissionType(DesignFormAuth auth, String permissionType) {
        if (checkPermissionType(permissionType)) {
            auth.setPermissionType(permissionType);
            return super.save(auth);
        }
        return false;
    }

    @Override
    public boolean editAuthByPermissionType(DesignFormAuth auth, String permissionType) {
        if (checkPermissionType(permissionType)) {
            auth.setPermissionType(permissionType);
            if (PermissionTypeEnum.BUTTON.getValue().equals(permissionType)) {
                return this.addOrEditButtonAuth(auth);
            } else {
                DesignFormAuth designFormAuthEntity = super.getById(auth.getId());
                if (designFormAuthEntity == null) {
                    throw new JeecgBootException("未找到对应实体");
                } else {
                    return super.updateById(auth);
                }
            }
        }
        return false;
    }

    /**
     * 添加或删除按钮权限
     */
    public boolean addOrEditButtonAuth(DesignFormAuth auth) {
        LambdaQueryWrapper<DesignFormAuth> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DesignFormAuth::getPermissionType, auth.getPermissionType());
        queryWrapper.eq(DesignFormAuth::getDesformId, auth.getDesformId());
        queryWrapper.eq(DesignFormAuth::getDesformCode, auth.getDesformCode());
        queryWrapper.eq(DesignFormAuth::getAuthField, auth.getAuthField());
        DesignFormAuth entity = super.getOne(queryWrapper);
        if (entity == null) {
            if (auth.getStatus() == null) {
                auth.setStatus(1);
            }
            return super.save(auth);
        } else {
            return super.update(auth, queryWrapper);
        }
    }

    @Override
    public JSONObject queryButtonsAuth(String desformCode, String username) {
        LambdaQueryWrapper<DesignFormAuth> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(DesignFormAuth::getPermissionType, PermissionTypeEnum.BUTTON.getValue());
        queryWrapper.eq(DesignFormAuth::getDesformCode, desformCode);
        queryWrapper.eq(DesignFormAuth::getStatus, 1);
        List<DesignFormAuth> entityList = super.list(queryWrapper);

        JSONObject userInfo = this.getUserInfoByUsername(username);
        return DesformAuthUtils.checkButtonsAuth(entityList, userInfo);
    }

    @Override
    public JSONArray queryDataAuth(String desformCode, String username, QueryWrapper<DesignFormData> queryWrapper, JSONArray superQueryList) {
        LambdaQueryWrapper<DesignFormAuth> getQueryWrapper = new LambdaQueryWrapper<>();
        getQueryWrapper.eq(DesignFormAuth::getPermissionType, PermissionTypeEnum.DATA.getValue());
        getQueryWrapper.eq(DesignFormAuth::getDesformCode, desformCode);
        getQueryWrapper.eq(DesignFormAuth::getStatus, 1);
        List<DesignFormAuth> entityList = super.list(getQueryWrapper);

        JSONObject allUserInfo = this.getUserInfoByUsername(username);
        JSONObject userInfo = allUserInfo.getJSONObject("userInfo");

        for (DesignFormAuth auth : entityList) {
            // 检查权限
            if (!DesformAuthUtils.checkOneDesformAuth(auth, allUserInfo)) {
                continue;
            }
            JSONObject queryItem = null;
            String field = auth.getAuthField();
            String val = auth.getAuthValue();
            // 替换 #{xxx} 变量
            val = QueryGenerator.getSqlRuleValue(val);

            // 判断是不是系统内置字段，如果是就不走 es 的查询
            if ("create_by".equals(field)
                    || "create_time".equals(field)
                    || "update_by".equals(field)
                    || "update_time".equals(field)
            ) {
                queryWrapper.eq(field, val);
            } else {
                boolean findIt = false;
                for (int i = 0; i < superQueryList.size(); i++) {
                    JSONObject temp = superQueryList.getJSONObject(i);
                    // 如果用户选择的高级查询和数据权限有冲突，那就走数据权限的规则
                    if (field.equals(temp.getString("field"))) {
                        // 直接覆盖高级查询的规则
                        queryItem = temp;
                        findIt = true;
                        break;
                    }
                }

                if (queryItem == null) {
                    queryItem = new JSONObject();
                }

                queryItem.put("field", field);
                queryItem.put("rule", auth.getAuthType());
                queryItem.put("val", val);

                if (!findIt) {
                    superQueryList.add(queryItem);
                }
            }
        }
        return superQueryList;
    }

    @Override
    public Result buildResultByPermissionType(
            String authScopeField,
            String authScopeCode,
            DesignFormAuth designFormAuth,
            String permissionType,
            String desformCode,
            HttpServletRequest request
    ) {
        PermissionTypeEnum perType = PermissionTypeEnum.getByValue(permissionType);
        if (perType != null) {
            // 为了防止查询条件生成器重复生成条件语句，所以设置为 null
            designFormAuth.setDesformCode(null);
            designFormAuth.setPermissionType(null);
            QueryWrapper<DesignFormAuth> queryWrapper = QueryGenerator.initQueryWrapper(designFormAuth, request.getParameterMap());
            queryWrapper.eq("desform_code", desformCode);
            queryWrapper.eq("permission_type", permissionType);
            //update-begin--Author:scott  Date:20201226 for：JT-314 授权范围是所有人的，角色授权界面不显示
            queryWrapper.ne("auth_scope_is_all", "Y");
            //update-end--Author:scott  Date:20201226 for：JT-314 授权范围是所有人的，角色授权界面不显示
            // 根据不同的授权类型，查询不同的数据，做出不同的处理
            if (PermissionTypeEnum.DATA == perType || PermissionTypeEnum.FIELD == perType) {
                return this.buildDataFieldResult(queryWrapper, authScopeField, authScopeCode, perType);
            } else if (PermissionTypeEnum.BUTTON == perType) {
                return this.buildButtonResult(queryWrapper, authScopeField, authScopeCode);
            }
        }
        return Result.error("不识别的permissionType值：" + permissionType);
    }

    @Override
    public Result buildDataFieldResult(QueryWrapper<DesignFormAuth> queryWrapper, String authScopeField, String authScopeCode, PermissionTypeEnum perType) {
        queryWrapper.eq("status", 1);
        // Step.1 查询出所有数据
        List<DesignFormAuth> allList = super.list(queryWrapper);
        // Step.2 查询出已授权的数据
        queryWrapper.and(i -> spliceAuthScopeWrapper(i, authScopeField, authScopeCode));
        List<DesignFormAuth> list = super.list(queryWrapper);
        // Step.3 合并两个数据并返回（返回值最小化）
        JSONArray records = new JSONArray();
        for (DesignFormAuth auth : allList) {
            JSONObject temp = new JSONObject(3);
            temp.put("key", auth.getId());
            String title = auth.getAuthTitle();
            //update-begin--Author:scott  Date:20201226 for：JT-314【表单设计器】角色授权的时候，字段罗列不清楚，没有区分主子表
            //字表标题
            if (auth.getSubTable()) {
                title = auth.getSubTitle() + "#" + title;
            }
            //update-end--Author:scott  Date:20201226 for：JT-314【表单设计器】角色授权的时候，字段罗列不清楚，没有区分主子表

            // 字段权限需要在标题上处理下可见或可编辑
            if (PermissionTypeEnum.FIELD == perType) {
                if ("1".equals(auth.getAuthType())) {
                    title += "（可见）";
                } else {
                    title += "（可编辑）";

                }
            }
            temp.put("title", title);
            temp.put("authField", auth.getAuthField());
            temp.put("scopeValue", auth.getAuthScopeRolesVal());
            temp.put("authScopeIsAll", auth.getAuthScopeIsAll());
            records.add(temp);
        }
        JSONObject result = new JSONObject(2);
        result.put("records", records);
        result.put("targetKeys", list.stream().map(DesignFormAuth::getId).collect(Collectors.toList()));
        return Result.ok(result);
    }


    @Override
    public Result buildButtonResult(QueryWrapper<DesignFormAuth> queryWrapper, String authScopeField, String authScopeCode) {
        // Step.1 查询出所有数据
        List<DesignFormAuth> allDbList = super.list(queryWrapper);
        List<DesignFormAuth> allButtonList = DesformAuthUtils.getNewButtonList();
        // 由于按钮有可能没有存到数据库，所以查出来的不一定是全部的数据，还需要合并一下
        List<DesignFormAuth> assignButtonList = DesformAuthUtils.assignButtonList(allButtonList, allDbList);
        // Step.2 查询出已授权的数据
        queryWrapper.and(i -> spliceAuthScopeWrapper(i, authScopeField, authScopeCode));
        List<DesignFormAuth> list = super.list(queryWrapper);
        // Step.3 合并两个数据并返回（返回值最小化）
        JSONArray records = new JSONArray();
        assignButtonList.forEach(auth -> {
            //update-begin--Author:scott  Date:20201226 for：JT-314 授权范围是所有人的，角色授权界面不显示
            if (auth.getStatus() == 1 && !"Y".equals(auth.getAuthScopeIsAll())) {
            //update-end--Author:scott  Date:20201226 for：JT-314 授权范围是所有人的，角色授权界面不显示
                JSONObject temp = new JSONObject(5);
                temp.put("key", auth.getId());
                temp.put("title", auth.getAuthTitle());
                temp.put("authField", auth.getAuthField());
                temp.put("scopeValue", auth.getAuthScopeRolesVal());
                temp.put("authScopeIsAll", auth.getAuthScopeIsAll());
                records.add(temp);
            }
        });
        JSONObject result = new JSONObject(2);
        result.put("records", records);
        result.put("targetKeys", list.stream().map(DesignFormAuth::getId).collect(Collectors.toList()));
        return Result.ok(result);

    }

    @Override
    public QueryWrapper<DesignFormAuth> spliceAuthScopeWrapper(QueryWrapper<DesignFormAuth> i, String fieldName, String code) {
        return i.eq(fieldName, code)
                .or().like(fieldName, "," + code + ",")
                .or().likeLeft(fieldName, "," + code)
                .or().likeRight(fieldName, code + ",");
    }

}
